# -*- encoding: utf-8 -*-

# Copyright 2010 István Szentandrási
# <etude-music-player@googlegroups.com>

# This file is part of Etude.
#
# Etude is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as 
# published by the Free Software Foundation, either version 3 
# of the License, or (at your option) any later version.
#
# Etude is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Etude. If not, see <http://www.gnu.org/licenses/>.

from . import _

import gtk
import gobject
import pango

import etude.plugins as ep
import etude.gui as eg



class DefaultEqualizer(ep.PluginPanel):

    _type = ep.E_PANEL_TYPE_EQU
    _short_name = "Equalizer"
    _show_name = _("Equalizer")
    _short_descr = ""
    _version = "0.1"
    _unique = "Default_Equalizer-0.1" # short name + version is enough, just to identify loaded
    _title = _("Equalizer")
    _config = {'preset': '', 'save_preset': '1', 'show_values': '0'}

    def __init__(self, control):
        ep.PluginPanel.__init__(self, control)
        self.client = control.get_client()
        self.set_label(_("Equalizer"))
        self.equ = None
        try:
            self.equ = self.client.plugins[u'equalizer']['instance']
            self.loaded_gui = False
            self.build_gui(True)
        except KeyError:
            self.loaded_gui = True
            self.build_gui(False)
        finally:
            self.bind( self.client, "e_plugin_loaded", self.e_plugin_loaded)
            self.bind( self.client, "e_plugin_unloaded", self.e_plugin_unloaded)

    
    def e_plugin_loaded(self, widget, shname):
        if shname == 'equalizer':
            self.equ = self.client.plugins[u'equalizer']['instance']
            self.build_gui()

    def e_plugin_unloaded(self, widget, shname):
        if shname == 'equalizer':
            self.build_gui(False)
            self.equ = None

    def build_gui(self, load_equ = True):
        """
        Create Frame showing the equalizer
        """

        if load_equ == False and self.loaded_gui == True:
            try:
                self.remove(self.vbox)
                self.unbind(self.equ, self.equ_changed_hid)
            except Exception, e:
                pass
            self.error_label = gtk.Label(_("The daemon doesn't have the equalizer plugin loaded"))
            self.error_label.show()
            self.add(self.error_label)
            self.loaded_gui = False
        elif load_equ == True and self.loaded_gui == False:
            try:
                self.remove(self.error_label)
            except Exception, e:
                pass

            self.vbox = gtk.VBox(False, 0)
            hbox1 = gtk.HBox(False, 0)
            self.enabled = gtk.CheckButton(_("Enable"))
            self.enabled.connect('toggled', self.set_enabled)
            hbox1.pack_start(self.enabled, False, False, 10)
            
            self.use_legacy = gtk.CheckButton(_("Use legacy"))
            self.use_legacy.connect('toggled', self.set_use_legacy)
            hbox1.pack_start(self.use_legacy, False, False, 5)

            self.extra_filtering = gtk.CheckButton(_("Extra filtering"))
            self.extra_filtering.connect('toggled', self.set_extra_filtering)
            hbox1.pack_start(self.extra_filtering, False, False, 10)
            hbox2 = gtk.HBox()
            hbox2.pack_start(gtk.Label(_("Bands")+": "), False, False, 0)
            self.bands = gtk.combo_box_new_text()
            self.bands.append_text('10')
            self.bands.append_text('15')
            self.bands.append_text('25')
            self.bands.append_text('31')
            self.bands.set_active(1)
            self.bands.connect("changed", self.set_bands)
            hbox2.pack_start(self.bands, False, False, 0)
            self.bands.show()
            
            self.remove_button = gtk.Button()
            eg.format_button(self.remove_button, force_image=True,
                    relief=gtk.RELIEF_NONE, stock_image=gtk.STOCK_REMOVE)
            self.remove_button.connect("clicked", self.remove_preset)
            hbox2.pack_end(self.remove_button, False, False, 0)

            self.custom = False #Custom is in the preset list
            self.save_button = gtk.Button(stock = gtk.STOCK_SAVE)
            self.save_button.connect("clicked", self.save_preset)
            hbox2.pack_end(self.save_button, False, False, 0)
            
            self.presets = gtk.combo_box_new_text()
            saved_preset = self.get_config('preset')
            active = False
            for preset in self.equ.presets:
                self.presets.append_text(preset)
                if preset == saved_preset and self.get_config('save_preset') == '1':
                    gobject.timeout_add_seconds(3, self.presets.set_active,
                            len(self.presets.get_model())-1)
                    active = True
            if not active:
                self.presets.prepend_text(_("Custom..."))
                self.custom = True
                self.presets.set_active(0)
            self.presets.connect("changed", self.set_presets)
            
            cell = self.presets.get_children()[0].get_cell_renderers()[0]
            cell.props.ellipsize = pango.ELLIPSIZE_END
            cell.props.width = 120
            
            hbox2.pack_end(self.presets, False, False, 0)
            hbox2.pack_end(gtk.Label(_("Presets")+": "), False, False, 0)
            self.presets.show()
            
            self.vbox.pack_start(hbox1, False, False, 0)
            self.vbox.pack_start(hbox2, False, False, 0)
            hbox1.show_all()
            hbox2.show_all()
            if not self.custom:
                self.save_button.hide()
            else:
                self.remove_button.hide()

            self.tcont = gtk.Table(2, 3, False)
            self.tcont.set_col_spacings(5)
            self.preamp = self.__create_vscale(-20, 20, 1, 5, self.set_preamp,
                    gtk.POS_TOP, True)
            self.preamp.show()
            self.gain = [self.__create_vscale(-20, 20, 1, 5, self.set_gain,
                gtk.POS_TOP, True) for i in xrange(31)]
            [g.set_size_request(-1, 100) for g in self.gain]
            [g.set_value_pos(gtk.POS_TOP) for g in self.gain]
            if self.get_config('show_values') == '1':
                [g.set_draw_value(True) for g in self.gain]
                self.preamp.set_draw_value(True)

            self.tcont.show()
            self.vbox.pack_start(self.tcont, False, False, 0)

            self.equ_changed(self.equ, "bands")
            self.equ_changed_hid = self.bind(self.equ, "e_changed",
                    self.equ_changed)
            self.equ.load_config()
             
            self.vbox.show()
            self.add(self.vbox)
            self.loaded_gui = True

    def equ_changed(self, widget, key, value = None):
        """
        Some of the equalizer settings changed on the server
        """
        if key == 'bands':
            a = (10, 15, 25, 31)
            self.bands.set_active(a.index(self.equ.bands))
            bands = '%d' % self.equ.bands
            if self.equ.use_legacy:
                bands = 'legacy'
            self.__clear_bands()
            self.__fill_bands(bands)
            self.presets.emit('changed')
        elif key == 'gain':
            if not self.equ.use_legacy:
                if self.gain[value].get_value() != self.equ.gain[value]:
                    self.gain[value].handler_block_by_func(self.set_gain)
                    self.gain[value].set_value(self.equ.gain[value])
                    self.gain[value].handler_unblock_by_func(self.set_gain)
        elif key == 'legacy':
            if self.equ.use_legacy:
                if self.gain[value].get_value() != self.equ.legacy[value]:
                    self.gain[value].handler_block_by_func(self.set_gain)
                    self.gain[value].set_value(self.equ.legacy[value])
                    self.gain[value].handler_unblock_by_func(self.set_gain)
        elif key == 'preamp':
            self.preamp.handler_block_by_func(self.set_preamp)
            self.preamp.set_value(self.equ.preamp)
            self.preamp.handler_unblock_by_func(self.set_preamp)
        elif key == 'extra_filtering':
            if self.equ.extra_filtering:
                self.extra_filtering.set_active(True)
            else:
                self.extra_filtering.set_active(False)
        elif key == 'use_legacy':
            if self.equ.use_legacy:
                self.use_legacy.set_active(True)
                self.bands.set_sensitive(False)
                self.__clear_bands()
                self.__fill_bands('legacy')
                for i in xrange(10):
                    self.gain[i].handler_block_by_func(self.set_gain)
                    self.gain[i].set_value(self.equ.legacy[i])
                    self.gain[i].handler_unblock_by_func(self.set_gain)
            else:
                self.use_legacy.set_active(False)
                self.bands.set_sensitive(True)
                self.equ_changed(widget, 'bands')
                for i in xrange(self.equ.bands):
                    self.gain[i].handler_block_by_func(self.set_gain)
                    self.gain[i].set_value(self.equ.gain[i])
                    self.gain[i].handler_unblock_by_func(self.set_gain)
        elif key == 'enabled':
            if self.equ.enabled:
                self.enabled.set_active(True)
                self.tcont.set_sensitive(True)
                self.extra_filtering.set_sensitive(True)
                self.use_legacy.set_sensitive(True)
                if not self.equ.use_legacy:
                    self.bands.set_sensitive(True)
                self.presets.set_sensitive(True)
                self.save_button.set_sensitive(True)
                self.remove_button.set_sensitive(True)
            else:
                self.enabled.set_active(False)
                self.tcont.set_sensitive(False)
                self.extra_filtering.set_sensitive(False)
                self.use_legacy.set_sensitive(False)
                self.bands.set_sensitive(False)
                self.presets.set_sensitive(False)
                self.save_button.set_sensitive(False)
                self.remove_button.set_sensitive(False)
                self.presets.emit('changed')

    def set_custom(self):
        if not self.custom:
            self.presets.prepend_text(_("Custom..."))
            self.presets.set_active(0)
            self.save_button.show()
            self.remove_button.hide()
            self.custom = True

    def __clear_bands(self):
        """
        clear the table containing the equalizer bands
        """
        for child in self.tcont.get_children():
            self.tcont.remove(child)
        self.tcont.attach(self.preamp, 0, 2, 0, 1,
                xoptions=gtk.FILL, yoptions=gtk.FILL)
        self.tcont.attach(gtk.Label(_("Preamp")), 0, 2, 1, 2,
                xoptions=gtk.FILL, yoptions=gtk.FILL)

    def __fill_bands(self, bands):
        """
        show all the band controls according the count of the bands
        """
        freqs = self.equ.freqs[bands]
        self.tcont.resize(2, 2+len(freqs))
        for i in xrange(len(freqs)):
            self.tcont.attach(self.gain[i], i+2, i+3, 0, 1,
                    xoptions=gtk.FILL, yoptions=gtk.FILL)
            self.tcont.attach(gtk.Label(freqs[i]), i+2, i+3, 1, 2,
                    xoptions=gtk.FILL, yoptions=gtk.FILL)
        self.tcont.show_all()
        self.queue_resize()

    def set_enabled(self, widget, data = None):
        """
        enable the equalizer on the client if the user want's it to
        """
        self.equ.enable(self.enabled.get_active())

    def set_presets(self, widget, data = None):
        """
        set the current preset
        """
        text = widget.get_active_text()
        if text == _("Custom..."):
            return
        if self.custom:
            widget.remove_text(0)
            self.custom = False
            self.save_button.hide()
            self.remove_button.show()
        if text:
            if self.equ.load_preset(text):
                self.set_config('preset', text)

    def set_bands(self, widget, data = None):
        """set the number of band controls"""
        a = (10, 15, 25, 31)
        self.equ.set_bands(a[widget.get_active()])
    
    def set_gain(self, widget, data = None):
        """set a gain"""
        try:
            ind = self.gain.index(widget)
        except ValueError:
            return False
        if self.equ.use_legacy:
            self.equ.set_legacy(ind, widget.get_value())
        else:
            self.equ.set_gain(ind, widget.get_value())
        self.set_custom()

    def set_preamp(self, widget, data = None):
        """set the preamp"""
        self.equ.set_preamp(widget.get_value())
        self.set_custom()

    def set_use_legacy(self, widget, data = None):
        """set if legacy controls are to be used"""
        self.equ.set_use_legacy(self.use_legacy.get_active())

    def set_extra_filtering(self, widget, data = None):
        """set if the daemon should use extra filtering on equalizer"""
        self.equ.set_extra_filtering(self.extra_filtering.get_active())

    def __create_vscale(self, rmin, rmax, step, page, handler, value_pos,
            inverted):
        """create a gain control"""
        vscale = gtk.VScale()
        vscale.set_range(rmin, rmax)
        vscale.set_increments(step, page)
        vscale.connect("value_changed", handler)
        if value_pos != None:
            vscale.set_value_pos(value_pos)
        vscale.set_draw_value(False)
        vscale.set_inverted(inverted)
        return vscale

    def save_preset(self, widget, data=None):
        dd = gtk.MessageDialog(parent=self.get_toplevel(), 
                flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
                type=gtk.MESSAGE_QUESTION,
                buttons=gtk.BUTTONS_OK_CANCEL)
        dd.set_markup(_("Preset name:"))
        entry = gtk.Entry(max=32)
        entry.set_text(_("New preset"))
        entry.show()
        dd.vbox.pack_start(entry)
        result = dd.run()
        preset_name = entry.get_text()
        if result == gtk.RESPONSE_OK and preset_name:
            model = self.presets.get_model()
            self.equ.save_preset(preset_name)
            if preset_name in model:
                pos = model.index(preset_name)
                self.presets.set_active(pos)
            else:
                self.presets.append_text(preset_name)
                self.presets.set_active(len(model)-1)
        dd.destroy()
    
    def remove_preset(self, widget, data=None):
        pos = self.presets.get_active()
        if pos == -1:
            return
        text = self.presets.get_active_text()
        self.presets.remove_text(pos)
        self.equ.remove_preset(text)
        self.set_custom()
        
